package com.guigu.exam.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.guigu.exam.entity.Category;
import com.guigu.exam.entity.Question;
import com.guigu.exam.exception.ExamException;
import com.guigu.exam.mapper.CategoryMapper;
import com.guigu.exam.mapper.QuestionMapper;
import com.guigu.exam.service.CategoryService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {
    @Autowired
    private QuestionMapper questionMapper;

    @Override
    public List<Category> getAllCategories() {
        //创建LambdaQueryWrapper对象
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        ////按照sort字段升序排序
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper1 = categoryLambdaQueryWrapper.orderByAsc(Category::getSort);
        //获取所有分类列表
        List<Category> categories = baseMapper.selectList(categoryLambdaQueryWrapper1);
        System.out.println("所有分类列表" + categories);
        //获取每个分类下的题目数量
        getQuestionCount(categories);
        return categories;
    }

    /*
     * 获取每个分类下的题目数量的方法*/
    private void getQuestionCount(List<Category> categories) {
        //获取所有分类下题目数量
        List<Map<Long, Long>> countList = questionMapper.getCategoryCount();
        System.out.println("countList=" + countList);
        //将 List<Map<Long, Long>>转换为Map<Long, Long>
        Map<Long, Long> countMap = countList.stream().collect(Collectors.toMap(
                m -> m.get("category_id"),
                m -> m.get("count(id)")
        ));
        System.out.println("countMap=" + countMap);
        //遍历所有分类列表
        categories.forEach(category -> {
            //根据分类ID获取题目数量
            Long questionCount = countMap.getOrDefault(category.getId(), 0L);
            //给分类设置题目数量
            category.setCount(questionCount);
        });
    }

    @Override
    public List<Category> getCategroyTree() {
        //获取所有分类列表,按照sort字段升序排序
        List<Category> categories = baseMapper.selectList(new LambdaQueryWrapper<Category>().orderByAsc(Category::getSort));
        //获取每个分类下的题目数量
        getQuestionCount(categories);
        //构建分类树结构
        List<Category> categoryTree = buildCategoryTree(categories);
        return categoryTree;
    }

    @Override
    public void saveCategory(Category category) {
        //根据父分类id和当前分类的名字查询父分类下是否已存在当前分类
        //创建LambdaQueryWrapper对象
        LambdaQueryWrapper<Category> categoryLambdaQueryWrapper = new LambdaQueryWrapper<>();
        //封装查询条件
        categoryLambdaQueryWrapper.eq(Category::getParentId, category.getParentId()).eq(Category::getName, category.getName());

        //调用带条件查询的方法
        Category isExistCategory = baseMapper.selectOne(categoryLambdaQueryWrapper);
        if (isExistCategory != null) {
            //获取父id
            Long parentId = category.getParentId();
            //根据父id查询父分类
            Category parentCategory = baseMapper.selectById(parentId);
            //获取父分类名称
            String parentName = parentCategory.getName();
            //证明当前父分类下已经存在该分类，抛出异常
            throw new ExamException(111, "父分类" + parentName + "下已存在" + category.getName() + "分类,请重新输入分类名称");


        }
        //保存该分类
        baseMapper.insert(category);
    }

    @Override
    public void updateCategory(Category category) {
        //根据当前分类的父id查询所有的子分类
        List<Category> childrenCategories = baseMapper.selectList(new LambdaQueryWrapper<Category>().eq(Category::getParentId, category.getParentId()));

        //获取所有子分类的名字
        List<String> childrenCategooriesNames = childrenCategories.stream().map(Category::getName).collect(Collectors.toList());
        //判断当前分类的名字是否在子分类的名字中
        if (childrenCategooriesNames.contains(category.getName())) {
            //获取数据库中和传入category名字一样的oldCategory
            Category oldCategory = baseMapper.selectOne(new LambdaQueryWrapper<Category>().eq(Category::getName, category.getName()));
            //判断更新的名称是不是还是原来的名称
            if (oldCategory.getId().equals(category.getId())) {
                //证明是自己，没有修改名称，可能是在修改其他字段，可以更新
                baseMapper.updateById(category);
            } else {
                //不是它自己
                //获取父id
                Long parentId = category.getParentId();

                //根据父id查询父分类
                Category parentCategory = baseMapper.selectById(parentId);
                //更新的子分类名称已经存在，抛出异常
                throw new ExamException(222, "父分类" + parentCategory.getName() + "下面已经存在" + category.getName() + "分类,请重新更新分类");
            }
        }


        //更新该分类
        baseMapper.updateById(category);
    }

    @Override
    public void removeCategory(Long id) {
        //判断该分类是否有子分类或者该分类下面是否有题目
        Long categoryCount = baseMapper.selectCount(new LambdaQueryWrapper<Category>().eq(Category::getParentId, id));
        Long questionCount = questionMapper.selectCount(new LambdaQueryWrapper<Question>().eq(Question::getCategoryId, id));
        if(categoryCount > 0 || questionCount > 0){
            //有子分类或者有题目，不能删除
            throw new ExamException(333, "该分类有子分类或者有题目，不能删除");
        }
        baseMapper.deleteById(id);
    }

    /*
     * 构建分类树结构的方法*/
    private List<Category> buildCategoryTree(List<Category> categories) {
        //按照parent_id分组，获取每个父分类下的子分类列表
        Map<Long, List<Category>> parentIdMap = categories.stream().collect(Collectors.groupingBy(Category::getParentId));
        System.out.println("parentIdMap=" + parentIdMap);

        //遍历所有的分类
        categories.forEach(category -> {
            //获取当前分类的id
            Long id = category.getId();
            //根据当前分类的id从Map中获取子分类列表
            List<Category> childrenCategories = parentIdMap.getOrDefault(id, new ArrayList<>());
            //将子分类列表设置到分类对象中
            category.setChildren(childrenCategories);
            //获取所有子分类的题目数量之和
            Long childrenSumQuestionCount = childrenCategories.stream().mapToLong(c -> c.getCount() != null ? c.getCount() : 0L).sum();

            //获取当前类型的题目的数量
            Long count = category.getCount();
            //设置当前分类题目的数量是子分类题目的数量之和加上当前分类的题目数量
            category.setCount(count + childrenSumQuestionCount);


        });
//获取顶级分类列表，即parent_id为0的分类
        List<Category> categoryTree = categories.stream().filter(category -> category.getParentId() == 0).collect(Collectors.toList());
        return categoryTree;
    }
}